home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The X-Philes (2nd Revision)
/
The X-Philes Number 1 (1995).iso
/
xphiles
/
hp48_2
/
chasm01.sha
/
link.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-03-23
|
8KB
|
523 lines
/*
* link.c - linked list routines
*
* @(#)link.c 1.1 91/04/10
*
* Copyright (c) 1991 Steve Scherf
*
* Author: Steve Scherf
* Date: Wed Apr 10 22:53:11 PDT 1991
*
*/
#include <stdio.h>
#include "chasm.h"
#define T_INST 0 /* instruction type link */
#define T_CON 1 /* constant type link */
#define T_STR 2 /* string type link */
#define T_PAD 3 /* pad type link */
struct link {
struct link *l_next;
int l_type;
int l_n;
union {
struct {
char *l_l;
int l_v;
int l_va;
} l;
struct {
int l_i[4];
int l_s[3];
} i;
struct {
struct link *l_c;
int l_con;
unsigned char *l_s;
} c;
} u;
};
#define l_line l_n
#define l_pad l_n
#define l_lab u.l.l_l
#define l_val u.l.l_v
#define l_valid u.l.l_va
#define l_op u.i.l_i
#define l_sz u.i.l_s
#define l_cp u.c.l_c
#define l_const u.c.l_con
#define l_len u.c.l_con
#define l_str u.c.l_s
struct link *lh; /* head of linked-list of labels */
struct link *lt; /* tail of linked-list of labels */
struct link *ih; /* head of linked-list of instructions */
struct link *it; /* tail of linked-list of instructions */
struct link *ch; /* head of linked-list of constants */
struct link *ct; /* tail of linked-list of constants */
struct link *get_lab_in();
struct link *smalloc();
int bcnt = LOADADR; /* output byte count */
int svin = -1; /* saved index of label to be defined */
extern int lineno;
/* set up linked lists */
init_links()
{
lh = smalloc(sizeof(struct link));
ih = smalloc(sizeof(struct link));
lh->l_next = lh;
lt = lh;
ih->l_next = ih;
it = ih;
ch = 0;
ct = 0;
}
/* add label to list if needed, return index */
int
add_lab(lab)
char *lab;
{
register struct link *l;
register int i;
for(i = 0, l = lh->l_next; l != lh; i++, l = l->l_next)
if(!strcmp(lab, l->l_lab))
return i;
l = smalloc(sizeof(struct link));
l->l_next = lh;
lt->l_next = l;
lt = l;
l->l_lab = (char *)smalloc(strlen(lab)+1);
strcpy(l->l_lab, lab);
l->l_val = 0;
l->l_valid = 0;
return i;
}
/* assign value to label by index */
add_val(in, val)
int in, val;
{
register int i;
register struct link *l;
for(i = 0, l = lh->l_next; i < in; i++)
l = l->l_next;
if(l->l_valid) {
lineno--;
yyerror("label multiply defined");
lineno++;
}
else {
l->l_valid = 1;
l->l_val = val;
}
}
/* get label by index */
struct link *
get_lab_in(in)
register int in;
{
register struct link *l;
for(l = lh->l_next; in; in--)
l = l->l_next;
return l;
}
/* check the size of the potential binary */
chk_size()
{
if(--bcnt > MAXADDR) {
printf("Error - program too large for address space ");
printf("(0x%X > 0x%3X)\n", bcnt, MAXADDR);
return 1;
}
return 0;
}
/* check the linked list of labels for any that are undefined */
chk_lab()
{
static int first = 1;
register struct link *l;
for(l = lh->l_next; l != lh; l = l->l_next)
if(!l->l_valid) {
if(first) {
printf("Error - undefined labels:\n");
first = 0;
}
printf("\t%s\n", l->l_lab);
}
return(!first);
}
/* check the value of constants to make sure they are in bounds */
chk_val()
{
register struct link *l, *lp;
register int x;
struct link *lp2;
int i, y, err = 0;
for(l = ih->l_next; l != ih; l = l->l_next)
switch(l->l_type) {
case T_CON:
for(lp = l->l_cp; lp; lp = lp->l_cp) {
x = lp->l_const;
if(x > 0xFFF) {
lp2 = get_lab_in((x >> 12)-1);
x = lp2->l_const;
}
if(x > 0xFF) {
print_ctl(lp->l_line, !err);
err = 1;
break;
}
}
break;
case T_INST:
for(i = 0; i < 3; i++) {
if(l->l_op[i+1] > 0xFFF) {
lp = get_lab_in((l->l_op[i+1] >> 12)-1);
x = lp->l_val;
}
else
x = l->l_op[i+1];
y = l->l_sz[i];
if(y < 0)
y++;
if(x >= (1 << (y * 4))) {
print_ctl(l->l_line, !err);
err = 1;
break;
}
}
break;
default:
break;
}
return err;
}
/* check to see if the last instruction is a label */
chk_var()
{
if(svin != -1)
add_val(svin, bcnt);
}
/* add instruction to list */
add_inst(line, a0, a1, s1, a2, s2, a3, s3)
int line, a0, a1, s1, a2, s2, a3, s3;
{
register struct link *l;
ct = ch;
if(svin != -1) {
add_val(svin, bcnt + (bcnt % 2));
svin = -1;
}
if(bcnt % 2)
add_pad(1);
l = smalloc(sizeof(struct link));
l->l_line = line;
l->l_type = T_INST;
l->l_op[0] = a0;
l->l_op[1] = a1;
l->l_op[2] = a2;
l->l_op[3] = a3;
l->l_sz[0] = s1;
l->l_sz[1] = s2;
l->l_sz[2] = s3;
l->l_next = ih;
it->l_next = l;
it = l;
bcnt += 2;
}
/* add constant to string list */
add_con(line, c)
int line, c;
{
if(!ch) {
ch = smalloc(sizeof(struct link));
ch->l_cp = 0;
ct = ch;
}
if(!ct->l_cp) {
ct->l_cp = smalloc(sizeof(struct link));
ct = ct->l_cp;
ct->l_cp = 0;
}
else
ct = ct->l_cp;
ct->l_type = T_CON;
ct->l_line = line;
ct->l_const = c;
}
/* add a string to linked list of constants */
add_str(line, s)
int line;
char *s;
{
int i;
if(!ch) {
ch = smalloc(sizeof(struct link));
ch->l_cp = 0;
ct = ch;
}
if(!ct->l_cp) {
ct->l_cp = smalloc(sizeof(struct link));
ct = ct->l_cp;
ct->l_cp = 0;
}
else
ct = ct->l_cp;
i = strlen(s);
ct->l_len = i;
ct->l_str = (unsigned char *)smalloc(++i);
strcpy(ct->l_str, s);
ct->l_type = T_STR;
ct->l_line = line;
}
/* add a byte pad directive to the linked list of instructions */
add_pad(n)
int n;
{
register struct link *l;
if(svin != -1) {
add_val(svin, bcnt);
svin = -1;
}
if(n > 0xFFF) {
n = n >> 12;
l = get_lab_in(--n);
if(!l->l_valid) {
yyerror("constant must be forward declared");
n = 0;
}
else
n = l->l_val;
}
bcnt += n;
ct = ch;
l = smalloc(sizeof(struct link));
l->l_type = T_PAD;
l->l_pad = n;
l->l_next = ih;
it->l_next = l;
it = l;
}
/* add a constant list directive to the linked list of instructions */
add_str_list()
{
register struct link *l;
register int i;
if(ch == ct)
return;
if(svin != -1) {
add_val(svin, bcnt);
svin = -1;
}
for(l = ch->l_cp, i = 0; l; l = l->l_cp)
if(l->l_type == T_STR)
i += l->l_len;
else
i++;
bcnt += i;
ch->l_type = T_CON;
ch->l_next = ih;
it->l_next = ch;
it = ch;
ch = ct->l_cp;
ct->l_cp = 0;
ct = ch;
}
/* output instructions accordingly */
out_inst(fp, asc)
FILE *fp;
int asc;
{
register struct link *l, *lp, *lp2;
register int y;
int i, x;
unsigned char c, *p;
for(l = ih->l_next; l != ih; l = l->l_next)
switch(l->l_type) {
case T_CON:
for(lp = l->l_cp; lp; lp = lp->l_cp) {
if(lp->l_type == T_STR) {
p = lp->l_str;
while(*p) {
if(asc) {
if(fprintf(fp, "%.2X",
*p) != 2)
return 0;
}
else
if(fwrite(p, 1, 1, fp)
!= 1)
return 0;
p++;
}
}
else {
y = lp->l_const;
if(y > 0xFFF) {
y = y >> 12;
lp2 = get_lab_in(--y);
y = lp2->l_val;
}
if(asc) {
if(fprintf(fp, "%.2X", y) != 2)
return 0;
}
else {
c = y;
if(fwrite(&c, 1, 1, fp) != 1)
return 0;
}
}
}
break;
case T_INST:
x = l->l_op[0] << 12;
for(i = 1; i < 4; i++) {
y = l->l_op[i];
if(y > 0xFFF) {
y = y >> 12;
lp = get_lab_in(--y);
y = lp->l_val;
}
x |= y << (12 - (i * 4));
}
if(asc) {
if(fprintf(fp, "%.4X", x) != 4)
return 0;
}
else {
c = x >> 8;
if(fwrite(&c, 1, 1, fp) != 1)
return 0;
c = x & 0xFF;
if(fwrite(&c, 1, 1, fp) != 1)
return 0;
}
break;
case T_PAD:
for(i = 0; i < l->l_pad; i++)
if(asc) {
if(fprintf(fp, "%.2X", 0) != 2)
return 0;
}
else {
c = 0;
if(fwrite(&c, 1, 1, fp) != 1)
return 0;
}
break;
}
return 1;
}
/* print constant size error list */
print_ctl(line, first)
int line, first;
{
if(first)
printf("Error - constant size:\n");
printf("\tline %d\n", line);
}
/* "safe" malloc */
struct link *
smalloc(size)
int size;
{
struct link *p;
if(!(p = (struct link *)malloc(size))) {
perror("malloc");
exit(1);
}
return p;
}